package learning.numbers.pro;



import java.util.ArrayList;
import java.util.Random;


import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;


public class ProGamePanel extends SurfaceView implements SurfaceHolder.Callback {
  
 private static final String TAG = ProGamePanel.class.getSimpleName();
 
 private GameThread thread;
 LearningNumbersActivity mkNumbersActivity= null; 
 public static final int numMoles = 9;
 private Paint paint = new Paint(Paint.FAKE_BOLD_TEXT_FLAG);
 
 private int screenHeight = 0; // Screen sizes
 private int screenWidth = 0;
 private int ballSize = 75;   //TODO add difficulty level with the ball size 
// private int marginHor = 0;   
// private int marginVert = 0;
// private int points = 0;      
 public Random r = new Random();
 public boolean firstRun = true;    
 public boolean free =  LearningNumbersActivity.Free;  //pro version or free version
 
 Resources res;
 
 private ArrayList<Ball> balls = new ArrayList<Ball>();
 public ArrayList<Integer> numbersOnScreen = new ArrayList<Integer>();
 public float scale = 0; 
 
 

 public ProGamePanel(Context c) {	 
  super(c);	    
  this.mkNumbersActivity = (LearningNumbersActivity) c;
  scale = (c.getResources().getDisplayMetrics().density) / 1.5f;
  getHolder().addCallback(this);
  res = c.getResources();
  // create the game loop thread
  thread = new GameThread(getHolder(),this);  
  setFocusable(true);      
  
  ballSize *=scale;
  
  //Generate Random Numbers for mole
  paint.setTextSize(30*scale);		
  paint.setARGB(200, 230, 230, 200);
  paint.setTextAlign(Paint.Align.CENTER);
  numbersOnScreen.add(-1);
 }
 
  
 

 private void setScreenSize() {
	this.screenHeight = getHeight();
	this.screenWidth = getWidth();	
}
 
 private void setBalls(){
	 	 
	 balls.clear();
	 numbersOnScreen.clear();
	 int ballsNumW = this.screenWidth / ballSize;
	 int remainingW = this.screenWidth % ballSize;
	 int marginW =  remainingW / (ballsNumW +1 );
	 
	 int ballsNumH = this.screenHeight / ballSize;
	 int remainingH = this.screenHeight % ballSize;
	 int marginH =  remainingH / (ballsNumH +1 );
//	 this.marginVert = marginH;  //not needed currently
//	 this.marginHor = marginW;
	 for (int i=0;i<ballsNumH;i++) {
		 int top = (i+1) * marginH + i*ballSize;
		 int bottom = (i+1) * marginH + (i+1)*ballSize;;
		 
		 for (int j=0;j<ballsNumW;j++){		 
			 Ball ball = new Ball(paint);
			 ball.setBounds((j+1)*marginW + j*ballSize, top, (j+1)*marginW + (j+1)*ballSize, bottom);
			 ball.setNumber();			 
			 balls.add(ball);
			 
		 }
	 }
	 
	 firstRun = false;
 }

 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {	 
	 thread.pauseGame();	 
	 setScreenSize();
	 setBalls();
	 mkNumbersActivity.setCurrentNumberTv();
	 Log.d(TAG,"surfaceChanged");
	 thread.unpauseGame();
 }

 
 public void surfaceCreated(SurfaceHolder holder) {		 
	
	
	 if(thread.getState()== Thread.State.TERMINATED){
		  Log.d(TAG, "new thread");
	      thread = new GameThread(getHolder(),this); 
	      thread.setRunning(true);
	      thread.start();      
	     }else {
	 thread.setRunning(true);  
	 thread.start();
	     }

	 }


public void update() {	
	// Nothing to update in this game so far.
	}

 
 public void surfaceDestroyed(SurfaceHolder holder) {
  boolean retry = true;
  while (retry) {
   try {		   
    thread.join();
    retry = false;
   } catch (InterruptedException e) {
    // try again shutting down the thread	   
   }
  }
 }

 
 public boolean isGamePaused(){
	 return thread.isPaused();
 }
 
 public void unpauseGame(){
	 Canvas canvas = getHolder().lockCanvas();
	 render(canvas);	
	 getHolder().unlockCanvasAndPost(canvas);
	 thread.unpauseGame();
 }
         

 public boolean onTouchEvent(MotionEvent motionEvent) {	 
	 //dumpEvent(motionEvent);
	 int action = motionEvent.getAction();
	 float x,y;	      
	 switch (action & MotionEvent.ACTION_MASK) {
	case MotionEvent.ACTION_DOWN:
		Log.d(TAG, "Coords: x=" + motionEvent.getX() + ",y=" + motionEvent.getY());
		   x =motionEvent.getX();
		   y = motionEvent.getY();
		   for (Ball ball : balls)
			   ball.handleActionDown(x,y);		   
		break;	
		
	case MotionEvent.ACTION_UP:
		Log.d(TAG, "Coords: x=" + motionEvent.getX() + ",y=" + motionEvent.getY());
		   x =motionEvent.getX();
		   y = motionEvent.getY();
		   for (Ball ball : balls)
			   ball.onRelease(x,y);		   
		break;	
	default:	
		break;
	}
	 return true;	 
 }
 
 public void stopPLaying(){  //the application will be put in background
	 thread.setRunning(false);
	  //((Activity)context).finish();
 }
 
 public void render(Canvas canvas) {
	 canvas.drawColor(Color.BLACK);
	 for (Ball ball : balls)		 
		 ball.draw(canvas);
	 }
	 

 public void resetNumbers(){
	 for (Ball ball : balls)
		 ball.setNumber();
 }
 
 public int getNextNumber() {		
		return numbersOnScreen.get(r.nextInt(numbersOnScreen.size()));
	}
 

 
 	
 	
 // To test touch events
 /*
  private void dumpEvent(MotionEvent event) {
 	   String names[] = { "DOWN" , "UP" , "MOVE" , "CANCEL" , "OUTSIDE" ,
 	      "POINTER_DOWN" , "POINTER_UP" , "7?" , "8?" , "9?" };
 	   StringBuilder sb = new StringBuilder();
 	   int action = event.getAction();
 	   int actionCode = action & MotionEvent.ACTION_MASK;
 	   sb.append("event ACTION_" ).append(names[actionCode]);
 	   if (actionCode == MotionEvent.ACTION_POINTER_DOWN
 	         || actionCode == MotionEvent.ACTION_POINTER_UP) {
 	      sb.append("(pid " ).append(
 	      action >> MotionEvent.ACTION_POINTER_ID_SHIFT);
 	      sb.append(")" );
 	   }
 	   sb.append("[" );
 	   for (int i = 0; i < event.getPointerCount(); i++) {
 	      sb.append("#" ).append(i);
 	      sb.append("(pid " ).append(event.getPointerId(i));
 	      sb.append(")=" ).append((int) event.getX(i));
 	      sb.append("," ).append((int) event.getY(i));
 	      if (i + 1 < event.getPointerCount())
 	         sb.append(";" );
 	   }
 	   sb.append("]" );
 	   Log.d(TAG, sb.toString());
 	}
 */
	
  private class Ball{
		
		Drawable ball;
		Drawable whiteball;
		private int number = -1;
		int left;
		int right;
		int top;
		int bottom;
		boolean touched = false;
		boolean shrinking = false;
		Paint inv,paint;
		
		Ball(Paint paint){
			this.ball = res.getDrawable(R.drawable.ball);
			this.whiteball = res.getDrawable(R.drawable.whiteball); 
			this.paint = paint;
			inv = new Paint();
			inv.setARGB(0, 0, 0, 0);
		}
		
		public void setNumber(){
			if (!firstRun)
				numbersOnScreen.remove((Object)this.number);
			this.number = r.nextInt(1999)+1;
			numbersOnScreen.add(this.number);
		}
		
		
		public void setBounds(int left,int top,int right,int bottom){
			this.left = left;
			this.right = right;
			this.top = top;
			this.bottom = bottom;
			ball.setBounds(left, top, right, bottom);
			whiteball.setBounds(left, top, right, bottom);
		}
		
		public void draw(Canvas canvas){
			if (!touched) {
				ball.setBounds(left, top, right, bottom); 	 			
				ball.draw(canvas);
			}
			else{ 
				if (!shrinking)
					whiteball.setBounds(left, top, right, bottom);
	 			whiteball.draw(canvas);
	 				 
				 
			}
			if (shrinking)
				canvas.drawText(""+number, (left+right)/2, (bottom+top)/2 + 10, inv);
			else
				canvas.drawText(""+number, (left+right)/2, (bottom+top)/2 + 10, paint);
			
		}
		
		public void handleActionDown(float x, float y){
			if (x > left && x < right) { 
				if (y> top && y < bottom) { 
					setTouched(true);		
				}else 
					setTouched(false);
			}else 
				setTouched(false);
		}
		
		
		public void onRelease(float x, float y){
			if (touched && mkNumbersActivity.checkAnswer(number)) { 				 			
				shrinking = true;
				int i=0;
				int left,top,right,bottom;
				left = this.left;
				top = this.top;
				right = this.right;
				bottom = this.bottom;
				int shrink_factor = 5;
				    while (true) {
				    	i++;
				    	left+=shrink_factor;
				    	top+=shrink_factor;
				    	right -= shrink_factor;
				    	bottom -=shrink_factor;
				    	this.whiteball.setBounds(left, top, right, bottom);
				    	whiteball.invalidateSelf();
				    	
				    	try {
							Thread.sleep(150);
						} catch (InterruptedException e) {							
							e.printStackTrace();
						}
				        if (i>10)
				        	break;
				    }
					mkNumbersActivity.updatePanel();
					this.ball = res.getDrawable(R.drawable.ball);
					ball.invalidateSelf();
					
			}
			setTouched(false); 		
			shrinking=false;
		}
		
		public void setTouched(boolean touch){
			touched = touch;
		} 		
}
  
 }
 




